home *** CD-ROM | disk | FTP | other *** search
- /* See the file Distribution for distribution terms.
- Copyright (c) 1994-1995 Ari Halberstadt */
-
- /* This file contains an interface to Thread Library that simulates Apple's
- Thread Manager. This interface allows you to easily switch between Apple's
- Thread Manager and my Thread Library. All routines and actions supported
- by Apple's Thread Manager, version 2.0, are supported by the routines in
- this library, with the exception of preemptive threads and thread pools.
- Operations on preemptive threads result in no-ops, and attempting to create
- a preemptive threads results in a threadProtocolErr, just as it would
- for the PowerPC version of Thread Manager. Since preemptive threads
- are not supported, thread pools are less important. Threads are always
- created using NewPtr and disposed of using DisposePtr; requests to
- create a thread from a pool, or to recycle a thread when it is
- disposed of, are ignored.
-
- The routines in this library have same the syntax as Thread Manager
- routines, and the names of the routines are the same except for the
- prefix "TLM". Thus, to create a new thread you would use TLMNewThread
- instead of NewThread.
-
- Warning: I have not tested every routine in this file. Use at your own risk. */
-
- #include <OSUtils.h>
- #include "ThreadLibrary.h"
- #include "ThreadLibraryManager.h"
-
- static struct {
- ThreadSchedulerProcPtr threadScheduler;
- DebuggerNewThreadProcPtr notifyNewThread;
- DebuggerDisposeThreadProcPtr notifyDisposeThread;
- DebuggerThreadSchedulerProcPtr notifyThreadScheduler;
- } gThread;
-
- typedef struct {
- ThreadType sn;
- ThreadID id;
-
- ThreadEntryProcPtr entry;
- void *entryParam;
- void **entryResult;
-
- ThreadSwitchProcPtr switcherIn;
- void *switcherInParam;
-
- ThreadSwitchProcPtr switcherOut;
- void *switcherOutParam;
-
- ThreadTerminationProcPtr terminator;
- void *terminatorParam;
-
- long critical;
- } ThreadManagerType;
-
- static OSErr ThreadIDToSN(ThreadID id, ThreadType *sn)
- {
- switch (id) {
- case kNoThreadID:
- *sn = THREAD_NONE;
- break;
- case kCurrentThreadID:
- *sn = ThreadActive();
- break;
- case kApplicationThreadID:
- *sn = ThreadMain();
- break;
- default:
- *sn = id - 2;
- break;
- }
- return(noErr);
- }
-
- static OSErr ThreadSNToID(ThreadType sn, ThreadID *id)
- {
- *id = sn + 2;
- return(noErr);
- }
-
- static OSErr ThreadSNToPtr(ThreadType sn, void **p)
- {
- *p = ThreadData(sn);
- return(ThreadError());
- }
-
- static OSErr ThreadIDToPtr(ThreadID id, void **p)
- {
- ThreadType sn;
- OSErr err;
-
- err = ThreadIDToSN(id, &sn);
- if (! err)
- err = ThreadSNToPtr(sn, p);
- return(err);
- }
-
- static ThreadType thread_scheduler(ThreadType suggested)
- {
- SchedulerInfoRec info;
- ThreadType active;
- OSErr err;
-
- if (gThread.threadScheduler) {
- info.InfoRecSize = sizeof(SchedulerInfoRec);
- info.InterruptedCoopThreadID = kNoThreadID;
- active = ThreadActive();
- err = ThreadError();
- if (! err) {
- err = ThreadSNToID(active, &info.CurrentThreadID);
- if (! err) {
- err = ThreadSNToID(suggested, &info.SuggestedThreadID);
- if (! err) {
- info.SuggestedThreadID = gThread.threadScheduler(&info);
- if (gThread.notifyThreadScheduler)
- info.SuggestedThreadID = gThread.notifyThreadScheduler(&info);
- err = ThreadIDToSN(info.SuggestedThreadID, &suggested);
- }
- }
- }
- if (err)
- suggested = THREAD_NONE;
- }
- return(suggested);
- }
-
- static void thread_begin(ThreadType sn, void *data)
- {
- ThreadManagerType *thread = data;
-
- if (gThread.notifyNewThread)
- gThread.notifyNewThread(thread->id);
- }
-
- static void thread_end(ThreadType sn, void *data)
- {
- ThreadManagerType *thread = data;
-
- if (thread->terminator)
- thread->terminator(thread->id, thread->terminatorParam);
- if (gThread.notifyDisposeThread)
- gThread.notifyDisposeThread(thread->id);
- }
-
- static void thread_suspend(void *data)
- {
- ThreadManagerType *thread = data;
-
- if (thread->switcherOut)
- thread->switcherOut(thread->id, thread->switcherOutParam);
- }
-
- static void thread_resume(void *data)
- {
- ThreadManagerType *thread = data;
-
- if (thread->switcherIn)
- thread->switcherIn(thread->id, thread->switcherInParam);
- }
-
- static void thread_entry(void *data)
- {
- ThreadManagerType *thread = data;
- void *result;
-
- if (thread->entry) {
- result = thread->entry(thread->entryParam);
- if (thread->entryResult)
- *thread->entryResult = result;
- }
- }
-
- OSErr TLMCreateThreadPool(ThreadStyle style, short count, Size stack)
- {
- return(noErr);
- }
-
- OSErr TLMGetFreeThreadCount(ThreadStyle style, short *count)
- {
- *count = 0;
- return(noErr);
- }
-
- OSErr TLMGetSpecificThreadCount(ThreadStyle style, Size stack, short *count)
- {
- *count = 0;
- return(noErr);
- }
-
- OSErr TLMGetDefaultThreadStackSize(ThreadStyle style, Size *size)
- {
- *size = ThreadStackDefault();
- return(ThreadError());
- }
-
- OSErr TLMThreadCurrentStackSpace(ThreadID id, long *free)
- {
- ThreadType sn;
- OSErr err;
-
- err = ThreadIDToSN(id, &sn);
- if (! err) {
- *free = ThreadStackSpace(sn);
- err = ThreadError();
- }
- return(err);
- }
-
- OSErr TLMNewThread(ThreadStyle style,
- ThreadEntryProcPtr entry,
- void *param,
- Size stack,
- ThreadOptions options,
- void **result,
- ThreadID *id)
- {
- ThreadManagerType *thread;
- ThreadType main;
- OSErr err;
-
- err = noErr;
- thread = NULL;
- if (style == kPreemptiveThread)
- err = threadProtocolErr;
- if (! err) {
-
- /* check if main thread exists */
- main = ThreadMain();
- err = ThreadError();
- if (! err && main == THREAD_NONE) {
-
- /* create main thread */
- thread = (ThreadManagerType *) NewPtrClear(sizeof(ThreadManagerType));
- if (! thread)
- err = (MemError() ? MemError() : memFullErr);
- if (! err) {
- thread->sn = ThreadBeginMain(NULL, NULL, thread);
- err = ThreadError();
- }
- if (err)
- DisposePtr((Ptr) thread);
- }
- if (! err) {
-
- /* allocate thread structure */
- thread = (ThreadManagerType *) NewPtrClear(sizeof(ThreadManagerType));
- if (! thread)
- err = (MemError() ? MemError() : memFullErr);
- if (! err) {
-
- /* allocate thread */
- thread->entry = entry;
- thread->entryParam = param;
- thread->entryResult = result;
- thread->sn = ThreadBegin(thread_entry, NULL, NULL, thread, stack);
- err = ThreadError();
- if (! err) {
-
- /* initialize thread */
- ThreadProcBeginSet(thread->sn, thread_begin);
- err = ThreadError();
- if (! err) {
- ThreadProcEndSet(thread->sn, thread_end);
- err = ThreadError();
- if (! err) {
- err = ThreadSNToID(thread->sn, &thread->id);
- if (! err) {
- if ((options & kNewSuspend) != 0) {
- ThreadEnabledSet(thread->sn, false);
- err = ThreadError();
- }
- }
- }
- }
- if (err) {
- ThreadEnd(thread->sn);
- thread->sn = THREAD_NONE;
- }
- }
- if (err) {
- DisposePtr((Ptr) thread);
- thread = NULL;
- }
- }
- }
- }
- *id = (thread ? thread->id : kNoThreadID);
- return(err);
- }
-
- OSErr TLMDisposeThread(ThreadID id, void *result, Boolean recycle)
- {
- ThreadManagerType *thread;
- ThreadType sn;
- OSErr err;
-
- err = noErr;
- if (id != kNoThreadID) {
- err = ThreadIDToSN(id, &sn);
- if (! err) {
- thread = ThreadData(sn);
- err = ThreadError();
- if (! err) {
- if (thread->entryResult)
- *thread->entryResult = result;
- ThreadEnd(sn);
- err = ThreadError();
- if (! err)
- DisposePtr((Ptr) thread);
- }
- }
- }
- return(err);
- }
-
- OSErr TLMGetCurrentThread(ThreadID *id)
- {
- ThreadType sn;
- OSErr err;
-
- sn = ThreadActive();
- err = ThreadError();
- if (! err)
- err = ThreadSNToID(sn, id);
- return(err);
- }
-
- OSErr TLMYieldToAnyThread(void)
- {
- if (ThreadMain() != THREAD_NONE)
- ThreadYield(0);
- return(ThreadError());
- }
-
- OSErr TLMThreadBeginCritical(void)
- {
- ThreadManagerType *thread;
- ThreadType sn;
- OSErr err;
-
- sn = ThreadActive();
- err = ThreadError();
- if (! err) {
- thread = ThreadData(sn);
- err = ThreadError();
- if (! err) {
- if (thread->critical == LONG_MAX)
- err = threadProtocolErr;
- if (! err)
- thread->critical++;
- }
- }
- return(err);
- }
-
- OSErr TLMThreadEndCritical(void)
- {
- ThreadManagerType *thread;
- ThreadType sn;
- OSErr err;
-
- sn = ThreadActive();
- err = ThreadError();
- if (! err) {
- thread = ThreadData(sn);
- err = ThreadError();
- if (! err) {
- if (thread->critical == 0)
- err = threadProtocolErr;
- if (! err)
- thread->critical--;
- }
- }
- return(err);
- }
-
- OSErr TLMYieldToThread(ThreadID id)
- {
- ThreadType sn;
- OSErr err;
-
- err = ThreadIDToSN(id, &sn);
- if (! err) {
- ThreadActivate(sn);
- err = ThreadError();
- }
- return(err);
- }
-
- OSErr TLMGetThreadState(ThreadID id, ThreadState *state)
- {
- ThreadType sn;
- OSErr err;
-
- err = ThreadIDToSN(id, &sn);
- if (! err) {
- if (sn == ThreadActive())
- *state = kRunningThreadState;
- else if (! ThreadEnabled(sn))
- *state = kStoppedThreadState;
- else
- *state = kReadyThreadState;
- }
- return(ThreadError());
- }
-
- OSErr TLMSetThreadState(ThreadID id, ThreadState state, ThreadID suggested)
- {
- ThreadType active;
- ThreadType main;
- ThreadType sn;
- OSErr err;
-
- main = ThreadMain();
- err = ThreadError();
- if (! err) {
- active = ThreadActive();
- err = ThreadError();
- if (! err) {
- err = ThreadIDToSN(id, &sn);
- if (! err) {
- switch (state) {
- case kRunningThreadState:
- if (sn != active) {
- ThreadActivate(sn);
- err = ThreadError();
- }
- break;
- case kStoppedThreadState:
- if (sn == main)
- err = threadProtocolErr;
- if (! err) {
- ThreadEnabledSet(sn, false);
- err = ThreadError();
- if (! err) {
- if (sn == active)
- ThreadActivate(suggested);
- }
- }
- break;
- case kReadyThreadState:
- if (sn == main)
- err = threadProtocolErr;
- if (! err) {
- ThreadEnabledSet(sn, true);
- err = ThreadError();
- if (! err) {
- if (sn == active)
- ThreadActivate(suggested);
- }
- }
- break;
- default:
- err = threadProtocolErr;
- break;
- }
- }
- }
- }
- return(err);
- }
-
- OSErr TLMSetThreadStateEndCritical(ThreadID id, ThreadState state, ThreadID suggested)
- {
- OSErr err;
-
- err = TLMThreadEndCritical();
- if (! err)
- err = TLMSetThreadState(id, state, suggested);
- return(err);
- }
-
- OSErr TLMGetThreadCurrentTaskRef(ThreadTaskRef *task)
- {
- *task = (ThreadTaskRef) SetCurrentA5();
- return(noErr);
- }
-
- OSErr TLMGetThreadStateGivenTaskRef(ThreadTaskRef task, ThreadID id, ThreadState *state)
- {
- long oldA5;
- OSErr err;
-
- oldA5 = SetA5((long) task);
- err = TLMGetThreadState(id, state);
- (void) SetA5(oldA5);
- return(err);
- }
-
- OSErr TLMSetThreadReadyGivenTaskRef(ThreadTaskRef task, ThreadID id)
- {
- ThreadState state;
- long oldA5;
- OSErr err;
-
- oldA5 = SetA5((long) task);
- err = TLMGetThreadStateGivenTaskRef(task, id, &state);
- if (! err) {
- if (state != kStoppedThreadState)
- err = threadProtocolErr;
- if (! err)
- TLMSetThreadState(id, state, kNoThreadID);
- }
- (void) SetA5(oldA5);
- return(err);
- }
-
- OSErr TLMSetThreadScheduler(ThreadSchedulerProcPtr scheduler)
- {
- OSErr err;
-
- ThreadProcScheduleSet(scheduler ? thread_scheduler : NULL);
- err = ThreadError();
- if (! err)
- gThread.threadScheduler = scheduler;
- return(err);
- }
-
- OSErr TLMSetThreadSwitcher(ThreadID id, ThreadSwitchProcPtr switcher,
- void *param, Boolean inout)
- {
- ThreadManagerType *thread;
- ThreadType sn;
- OSErr err;
-
- err = ThreadIDToSN(id, &sn);
- if (! err) {
- thread = ThreadData(sn);
- err = ThreadError();
- if (! err) {
- if (inout) {
- ThreadProcResumeSet(sn, switcher ? thread_resume : NULL);
- err = ThreadError();
- if (! err) {
- thread->switcherIn = switcher;
- thread->switcherInParam = param;
- }
- }
- else {
- ThreadProcSuspendSet(sn, switcher ? thread_suspend : NULL);
- err = ThreadError();
- if (! err) {
- thread->switcherOut = switcher;
- thread->switcherOutParam = param;
- }
- }
- }
- }
- return(err);
- }
-